package com.greenway.tools;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;


public class StepDiscret {
	public static List<Location> getAllLocations(int precise, List<Step> stepList){
		//Initialize standard coordinate's precision 
    	final int dec = 6;
    	//Create precisions to #precise after comma 
    	precise = (int) Math.pow(10,precise);
    	List<Location> points = new ArrayList<Location>();
    	for(Step step : stepList){
    		
    		Location startLoc = step.getStart_location();
    		Location endLoc = step.getEnd_location();
    		
    		BigDecimal startLat = new BigDecimal(startLoc.getLat());
    		BigDecimal startLng = new BigDecimal(startLoc.getLng());
    		//Get all start and end coordinates
    		BigDecimal endLat = new BigDecimal(endLoc.getLat());
    		BigDecimal endLng = new BigDecimal(endLoc.getLng());
    		
    		int horizontal;
    		boolean endLatBigger = false;
    		BigDecimal biggerLat = endLat.max(startLat);
    		BigDecimal smallerLat = endLat.min(startLat);
    		if(biggerLat.equals(endLat)){
    			endLatBigger = true;	//Remember which one was bigger
    		}
    		BigDecimal resultLat = biggerLat.subtract(smallerLat);
    		
    		horizontal = resultLat.multiply(new BigDecimal(precise)).intValue();	//Calculate horizontal sampling
    		
    		int vertical;
    		boolean endLngBigger = false;
    		BigDecimal biggerLng = endLng.max(startLng);
    		BigDecimal smallerLng = endLng.min(startLng);
    		if(biggerLng.equals(endLng)){
    			endLngBigger = true;	//Remember which one was bigger
    		}
    		BigDecimal resultLng = biggerLng.subtract(smallerLng);
    		
			vertical = resultLng.multiply(new BigDecimal(precise)).intValue();	//Calculate vertical sampling
    		
    		int avg = (horizontal + vertical) / 2;		//Calculate average sampling
    		
    		if(avg <= 0)
    			avg = 1;	//Consider short distances (less than sampling gaps)
    		
    		//Calculate period in coordinates
    		BigDecimal periodLat = resultLat.divide(new BigDecimal(avg), dec, RoundingMode.UP);
    		BigDecimal periodLng = resultLng.divide(new BigDecimal(avg), dec, RoundingMode.UP);
    		
    		for(int i = 0; i<avg; i++){
    			//Create new point for the rout
    			Location point = new Location();
    			
    			//Northeast
    			if(endLatBigger&&endLngBigger){
	    			if(points.isEmpty()){	//Summarize start coordinate with period
	    				point.setLat(startLat.add(periodLat).setScale(dec, RoundingMode.UP).doubleValue());
	    				point.setLng(startLng.add(periodLng).setScale(dec, RoundingMode.UP).doubleValue());
	    			}else{					//Summarize previous coordinate with period
	    				point.setLat(new BigDecimal(points.get(points.size()-1).getLat()).add(periodLat).setScale(dec, RoundingMode.UP).doubleValue());
	    				point.setLng(new BigDecimal(points.get(points.size()-1).getLng()).add(periodLng).setScale(dec, RoundingMode.UP).doubleValue());
	    			}
    			}
    			//Southwest
    			else if (!endLatBigger&&!endLngBigger){
    				if(points.isEmpty()){	//Summarize start coordinate with period
	    				point.setLat(startLat.subtract(periodLat).setScale(dec, RoundingMode.UP).doubleValue());
	    				point.setLng(startLng.subtract(periodLng).setScale(dec, RoundingMode.UP).doubleValue());
	    			}else{					//Summarize previous coordinate with period
	    				point.setLat(new BigDecimal(points.get(points.size()-1).getLat()).subtract(periodLat).setScale(dec, RoundingMode.UP).doubleValue());
	    				point.setLng(new BigDecimal(points.get(points.size()-1).getLng()).subtract(periodLng).setScale(dec, RoundingMode.UP).doubleValue());
	    			}
    			}
    			//Northwest
    			else if (endLatBigger&&!endLngBigger){
    				if(points.isEmpty()){	//Summarize start coordinate with period
	    				point.setLat(startLat.add(periodLat).setScale(dec, RoundingMode.UP).doubleValue());
	    				point.setLng(startLng.subtract(periodLng).setScale(dec, RoundingMode.UP).doubleValue());
	    			}else{					//Summarize previous coordinate with period
	    				point.setLat(new BigDecimal(points.get(points.size()-1).getLat()).add(periodLat).setScale(dec, RoundingMode.UP).doubleValue());
	    				point.setLng(new BigDecimal(points.get(points.size()-1).getLng()).subtract(periodLng).setScale(dec, RoundingMode.UP).doubleValue());
	    			}
    			}
    			//Southeast
    			else if (!endLatBigger&&endLngBigger){
    				if(points.isEmpty()){	//Summarize start coordinate with period
	    				point.setLat(startLat.subtract(periodLat).setScale(dec, RoundingMode.UP).doubleValue());
	    				point.setLng(startLng.add(periodLng).setScale(dec, RoundingMode.UP).doubleValue());
	    			}else{					//Summarize previous coordinate with period
	    				point.setLat(new BigDecimal(points.get(points.size()-1).getLat()).subtract(periodLat).setScale(dec, RoundingMode.UP).doubleValue());
	    				point.setLng(new BigDecimal(points.get(points.size()-1).getLng()).add(periodLng).setScale(dec, RoundingMode.UP).doubleValue());
	    			}
    			}
    			//Add point to the list
    			points.add(point);
    		}
    	}
    	return points;
    }
}
